import os
import requests
from dotenv import load_dotenv
from prompt_manager import PromptManager
import logging
import json

# 配置日志
logger = logging.getLogger(__name__)

# 加载.env文件中的环境变量
load_dotenv()

class DeepSeekAPI:
    """
    DeepSeek API 客户端类，用于与DeepSeek API进行交互
    """
    def __init__(self, api_key=None, base_url=None):
        # 优先使用传入的参数，否则从环境变量中读取
        self.api_key = api_key or os.getenv("DEEPSEEK_API_KEY")
        self.base_url = base_url or os.getenv("DEEPSEEK_BASE_URL", "https://api.deepseek.com/v1")
        
        if not self.api_key:
            raise ValueError("DeepSeek API密钥未设置，请在.env文件中配置DEEPSEEK_API_KEY或在初始化时提供")
        
        # 初始化 prompt 管理器
        self.prompt_manager = PromptManager()
        logger.info(f"DeepSeek API 初始化完成，使用基础URL: {self.base_url}")
    
    def _read_text_file(self, text_path):
        """
        读取文本文件内容
        
        参数:
            text_path (str): 文本文件的路径
            
        返回:
            str: 文件内容
        """
        try:
            if not os.path.exists(text_path):
                logger.error(f"文本文件不存在: {text_path}")
                return None
                
            with open(text_path, 'r', encoding='utf-8') as f:
                content = f.read()
                logger.info(f"成功读取文本文件，内容长度: {len(content)} 字符")
                return content
        except Exception as e:
            logger.error(f"读取文本文件失败: {str(e)}", exc_info=True)
            return None
            
    def process(self, text, prompt_type="translate", target_lang="en", custom_prompt=None, **kwargs):
        """
        通用处理方法，根据prompt类型选择相应的处理函数
        
        参数:
            text (str or dict): 要处理的文本或包含文本路径的字典
            prompt_type (str): prompt类型，可选值: translate, summarize, extract_info, qa, format_markdown
            target_lang (str): 目标语言代码
            custom_prompt (str): 自定义的prompt，如果提供则优先使用
            **kwargs: 传递给特定处理函数的其他参数
            
        返回:
            str: 处理后的文本
        """
        # 处理输入可能是字典的情况（OCR结果）
        if isinstance(text, dict) and 'file_info' in text:
            text_path = text['file_info'].get('text_path')
            if text_path:
                logger.info(f"从文件读取OCR文本: {text_path}")
                file_content = self._read_text_file(text_path)
                if file_content is None:
                    return "错误: 无法读取OCR文本文件"
                text = file_content
            else:
                logger.error("OCR结果中未找到text_path")
                return "错误: OCR结果中未找到文本文件路径"
                
        logger.info(f"开始处理文本 - 类型: {prompt_type}, 目标语言: {target_lang}")
        logger.info(f"文本长度: {len(text)} 字符")
        logger.info(f"其他参数: {json.dumps(kwargs, ensure_ascii=False, indent=2)}")
        
        # 如果存在自定义prompt，直接使用
        if custom_prompt:
            logger.info("使用自定义prompt")
            return self._call_model(custom_prompt)
        
        # 根据prompt类型选择不同的处理函数
        try:
            if prompt_type == "translate":
                return self.translate(text, target_lang=target_lang, **kwargs)
            elif prompt_type == "summarize":
                summary_length = kwargs.get("summary_length", 500)
                logger.info(f"使用总结功能，目标长度: {summary_length}")
                return self.summarize(text, target_lang=target_lang, summary_length=summary_length)
            elif prompt_type == "extract_info":
                query = kwargs.get("query", "")
                if not query:
                    logger.error("使用extract_info需要提供query参数")
                    return "错误: 使用信息提取功能需要提供查询内容"
                return self.extract_info(text, query=query, target_lang=target_lang)
            elif prompt_type == "qa":
                query = kwargs.get("query", "")
                if not query:
                    logger.error("使用qa需要提供query参数")
                    return "错误: 使用问答功能需要提供问题内容"
                return self.qa(text, query=query, target_lang=target_lang)
            elif prompt_type == "format_markdown":
                return self.format_markdown(text, target_lang=target_lang)
            else:
                logger.warning(f"未知的prompt类型: {prompt_type}，默认使用translate")
                return self.translate(text, target_lang=target_lang)
        except Exception as e:
            logger.error(f"处理文本时发生错误: {str(e)}", exc_info=True)
            raise
    
    def translate(self, text, source_lang="auto", target_lang="en"):
        """
        翻译文本
        
        参数:
            text (str): 要翻译的文本
            source_lang (str): 源语言代码，默认为auto自动检测
            target_lang (str): 目标语言代码，默认为en英语
            
        返回:
            str: 翻译后的文本
        """
        logger.info(f"准备翻译文本，源语言: {source_lang}, 目标语言: {target_lang}")
        logger.info(f"文本长度: {len(text)} 字符")
        logger.info(f"文本预览: {text[:200]}...")
        
        # 获取翻译的 prompt
        prompt = self.prompt_manager.get_prompt(
            "translate",
            target_language=target_lang,
            source_text=text  # 确保传递文本内容
        )
        
        # 如果没有找到 prompt 模板，使用默认方式
        if not prompt:
            logger.warning("未找到翻译 prompt 模板，使用默认翻译方式")
            return self._translate_default(text, source_lang, target_lang)
            
        logger.info("成功生成翻译 prompt")
        logger.info(f"Prompt 预览: {prompt[:200]}...")
            
        # 使用 prompt 调用大模型
        return self._call_model(prompt)
    
    def summarize(self, text, target_lang="zh", summary_length=500):
        """
        总结文本
        
        参数:
            text (str): 要总结的文本
            target_lang (str): 输出语言代码，默认为zh中文
            summary_length (int): 总结的最大长度，默认为500字
            
        返回:
            str: 总结后的文本
        """
        logger.info(f"准备总结文本，目标语言: {target_lang}, 总结长度: {summary_length}")
        logger.info(f"文本长度: {len(text)} 字符")
        logger.info(f"文本预览: {text[:200]}...")
        
        # 获取总结的 prompt
        prompt = self.prompt_manager.get_prompt(
            "summarize",
            target_language=target_lang,  # 模板中使用 {target_language}
            summary_length=str(summary_length),  # 模板中使用 {summary_length}
            source_text=text.strip()  # 模板中使用 {source_text}，去除首尾空白字符
        )
        
        if not prompt:
            logger.error("未找到总结 prompt 模板或参数不完整")
            return "无法生成总结：prompt 模板不存在或参数不完整"
            
        logger.info("成功生成总结 prompt")
        logger.info(f"Prompt 预览: {prompt[:200]}...")
            
        # 使用 prompt 调用大模型
        return self._call_model(prompt, max_tokens=min(summary_length * 2, 2048))  # 确保有足够的token生成总结
    
    def extract_info(self, text, query, target_lang="zh"):
        """
        从文本中提取特定信息
        
        参数:
            text (str): 源文本
            query (str): 要提取的信息查询
            target_lang (str): 输出语言代码，默认为zh中文
            
        返回:
            str: 提取的信息
        """
        logger.info(f"准备提取信息，查询: {query}, 目标语言: {target_lang}")
        logger.info(f"文本长度: {len(text)} 字符")
        logger.info(f"文本预览: {text[:200]}...")
        
        # 获取信息提取的 prompt
        prompt = self.prompt_manager.get_prompt(
            "extract_info",
            query=query,
            target_language=target_lang,
            source_text=text  # 确保传递文本内容
        )
        
        # 如果没有找到 prompt 模板，返回错误
        if not prompt:
            logger.error("未找到信息提取 prompt 模板")
            return f"无法提取信息：prompt 模板不存在"
            
        logger.info("成功生成信息提取 prompt")
        logger.info(f"Prompt 预览: {prompt[:200]}...")
            
        # 使用 prompt 调用大模型
        return self._call_model(prompt)
    
    def qa(self, text, query, target_lang="zh"):
        """
        基于文档内容回答问题
        
        参数:
            text (str): 文档内容
            query (str): 问题
            target_lang (str): 输出语言代码，默认为zh中文
            
        返回:
            str: 回答内容
        """
        logger.info(f"准备回答问题，问题: {query}, 目标语言: {target_lang}")
        logger.info(f"文本长度: {len(text)} 字符")
        logger.info(f"文本预览: {text[:200]}...")
        
        # 获取问答的 prompt
        prompt = self.prompt_manager.get_prompt(
            "qa",
            query=query,
            target_language=target_lang,
            source_text=text  # 确保传递文本内容
        )
        
        # 如果没有找到 prompt 模板，返回错误
        if not prompt:
            logger.error("未找到问答 prompt 模板")
            return f"无法回答问题：prompt 模板不存在"
            
        logger.info("成功生成问答 prompt")
        logger.info(f"Prompt 预览: {prompt[:200]}...")
            
        # 使用 prompt 调用大模型
        return self._call_model(prompt)
    
    def format_markdown(self, text, target_lang="zh"):
        """
        将文本转换为格式良好的 Markdown
        
        参数:
            text (str): 要格式化的原始文本
            target_lang (str): 输出语言代码，默认为zh中文
            
        返回:
            str: 格式化后的 Markdown 文本
        """
        logger.info(f"准备格式化为Markdown，目标语言: {target_lang}")
        logger.info(f"文本长度: {len(text)} 字符")
        logger.info(f"文本预览: {text[:200]}...")
        
        # 获取 Markdown 格式化的 prompt
        prompt = self.prompt_manager.get_prompt(
            "format_markdown",
            target_language=target_lang,
            source_text=text  # 确保传递文本内容
        )
        
        # 如果没有找到 prompt 模板，返回错误
        if not prompt:
            logger.error("未找到 Markdown 格式化 prompt 模板")
            return text  # 返回原始文本
            
        logger.info("成功生成Markdown格式化 prompt")
        logger.info(f"Prompt 预览: {prompt[:200]}...")
            
        # 使用 prompt 调用大模型
        return self._call_model(prompt)
    
    def _translate_default(self, text, source_lang="auto", target_lang="en"):
        """
        使用默认翻译 API 进行翻译（不使用 prompt）
        
        参数:
            text (str): 要翻译的文本
            source_lang (str): 源语言代码，默认为auto自动检测
            target_lang (str): 目标语言代码，默认为en英语
            
        返回:
            str: 翻译后的文本
        """
        endpoint = f"{self.base_url}/translate"
        
        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }
        
        payload = {
            "text": text,
            "source_language": source_lang,
            "target_language": target_lang
        }
        
        try:
            response = requests.post(endpoint, headers=headers, json=payload)
            response.raise_for_status()  # 如果请求失败，抛出异常
            
            result = response.json()
            return result.get("translated_text", "")
        except requests.exceptions.RequestException as e:
            logger.error(f"翻译请求失败: {e}")
            return text  # 如果失败，返回原始文本
    
    def _call_model(self, prompt, temperature=0.7, max_tokens=2048):
        """
        调用 DeepSeek 大模型 API
        
        参数:
            prompt (str): 提示词
            temperature (float): 温度参数，控制输出的随机性
            max_tokens (int): 最大生成的 token 数量
            
        返回:
            str: 模型生成的回复
        """
        endpoint = f"{self.base_url}/chat/completions"
        
        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }
        
        payload = {
            "model": "deepseek-chat",
            "messages": [
                {"role": "user", "content": prompt}
            ],
            "temperature": temperature,
            "max_tokens": max_tokens
        }
        
        # 记录请求信息（不包含API密钥）
        log_headers = headers.copy()
        log_headers["Authorization"] = "Bearer ********"  # 隐藏API密钥
        
        logger.info(f"准备调用大模型API - Endpoint: {endpoint}")
        logger.info(f"请求头: {json.dumps(log_headers, ensure_ascii=False, indent=2)}")
        logger.info(f"请求参数: {json.dumps(payload, ensure_ascii=False, indent=2)}")
        
        try:
            response = requests.post(endpoint, headers=headers, json=payload)
            response.raise_for_status()
            
            result = response.json()
            logger.info(f"API响应状态码: {response.status_code}")
            logger.info(f"API响应内容: {json.dumps(result, ensure_ascii=False, indent=2)}")
            
            content = result.get("choices", [{}])[0].get("message", {}).get("content", "")
            if content:
                preview = content[:200] + "..." if len(content) > 200 else content
                logger.info(f"生成的内容预览: {preview}")
            else:
                logger.warning("API返回的内容为空")
            
            return content
            
        except requests.exceptions.RequestException as e:
            logger.error(f"调用大模型API失败: {str(e)}", exc_info=True)
            if hasattr(e.response, 'json'):
                try:
                    error_detail = e.response.json()
                    logger.error(f"API错误详情: {json.dumps(error_detail, ensure_ascii=False, indent=2)}")
                except:
                    logger.error(f"API错误响应: {e.response.text}")
            raise


# 使用示例
if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO)
    
    # 初始化 DeepSeek API
    deepseek = DeepSeekAPI()
    
    # 测试翻译功能
    text_to_translate = "这是一个测试文本，用于测试 DeepSeek API 的翻译功能。"
    translated_text = deepseek.translate(text_to_translate)
    print(f"翻译结果: {translated_text}")
    
    # 测试总结功能
    text_to_summarize = """
    这是一个较长的测试文本，包含多个段落和详细信息。
    用于测试 DeepSeek API 的总结功能。
    这个文本应该足够长，以便能够生成一个有意义的总结。
    总结应该能够提取出这段文本中的关键信息，并以简洁的方式呈现出来。
    """
    summary = deepseek.summarize(text_to_summarize)
    print(f"总结结果: {summary}") 